<?php

namespace Xin\WorkmanServer\Laravel\Console;

use Illuminate\Console\Command;
use Xin\Support\Reflect;
use Xin\WorkmanServer\HttpServer;
use Xin\WorkmanServer\Server;
use Xin\WorkmanServer\WebsocketServer;
use Xin\WorkmanServer\WorkerUtil;

class ServerCommand extends Command
{
	/**
	 * @var string
	 */
	protected $signature = 'workerman:server {action} {--daemon}';

	/**
	 * @var string
	 */
	protected $description = 'Start [http,websocket] Server.';

	/**
	 * Execute the console command.
	 *
	 * @return int
	 * @throws \ReflectionException
	 * @see https://learnku.com/users/31554
	 */
	public function handle()
	{
		global $argv;

		if (!in_array($action = $this->argument('action'), ['start', 'stop', 'restart'])) {
			$this->error('Error Arguments');
			exit;
		}

		$argv[0] = 'workerman:server';
		$argv[1] = $action;
		$argv[2] = $this->option('daemon') ? '-d' : '';

		$this->start();

		return self::SUCCESS;
	}

	/**
	 * @return void
	 * @throws \ReflectionException
	 */
	protected function start()
	{
		$this->startHttpServer();
		$this->startWebsocketServer();
		$this->startProcessList();

		$this->info('Workerman Server Started.');

		Server::runAll();
	}

	/**
	 * 启动HttpServer
	 * @return HttpServer
	 * @throws \ReflectionException
	 */
	protected function startHttpServer()
	{
		if (!$this->laravel->has('http_server')) {
			return null;
		}

		return tap($this->laravel['http_server'], function (HttpServer $httpServer) {
			if ($httpServer->getConfig('enable')) {
				Reflect::set($this->laravel, 'isRunningInConsole', false);
				// $this->laravel->setRunningInConsole(false);
				$httpServer->run();
			}
		});
	}

	/**
	 * @return null|WebsocketServer
	 */
	protected function startWebsocketServer()
	{
		if (!$this->laravel->has('websocket_server')) {
			return null;
		}

		return tap($this->laravel['websocket_server'], function (WebsocketServer $websocketServer) {
			if ($websocketServer->getConfig('enable')) {
				$websocketServer->run();
			}
		});
	}

	/**
	 * @return array
	 */
	protected function startProcessList()
	{
		$processList = config('workerman.process', []);

		$workers = [];
		foreach ($processList as $processConfig) {
			$workerName = $processConfig['name'] ?? WorkerUtil::getWorkerName($processConfig);
			$worker = WorkerUtil::start($workerName, $processConfig);
			$workers[] = $worker;
		}

		return $workers;
	}
}
